tg-me.com/data_analysis_ml/3540
Last Update:
🧩 Задача для продвинутых дата-сайентистов: "Парадокс усечённых данных"
📖 Описание задачи
У вас есть DataFrame df
с данными о зарплатах сотрудников в компании:
import pandas as pd
data = {
'employee_id': range(1, 11),
'department': ['IT', 'IT', 'IT', 'HR', 'HR', 'Finance', 'Finance', 'Finance', 'Finance', 'Finance'],
'salary': [120000, 125000, None, 70000, None, 90000, None, 95000, None, 100000]
}
df = pd.DataFrame(data)
print(df)
Результат:
employee_id department salary
0 1 IT 120000.0
1 2 IT 125000.0
2 3 IT NaN
3 4 HR 70000.0
4 5 HR NaN
5 6 Finance 90000.0
6 7 Finance NaN
7 8 Finance 95000.0
8 9 Finance NaN
9 10 Finance 100000.0
👉 В задаче требуется:
> **Заполнить пропущенные зарплаты медианой по департаменту.
> Затем найти департамент с наибольшим средним уровнем зарплаты.**
Вы пишете такой код:
df['salary_filled'] = df.groupby('department')['salary'].transform(lambda x: x.fillna(x.median()))
top_department = df.groupby('department')['salary_filled'].mean().idxmax()
print(top_department)
❗️ Результат: "Finance"
Но через неделю выясняется, что HR утверждает:
> “Наш средний уровень зарплаты выше, чем в Finance!”
📝 Ваша задача:
1. Объяснить почему результат показывает Finance, хотя HR утверждает обратное?
2. Где ошибка в логике?
3. Как правильно посчитать среднюю зарплату, учитывая реальную ситуацию?
---
🎯 Подвох (ключевой момент):
Медиана по HR = 70000 (только одно известное значение).
Пропущенная зарплата в HR тоже заполняется 70000, т.е. обе записи будут 70000.
В Finance медиана = 95000 (из трёх известных: 90000, 95000, 100000).
Две пропущенные зарплаты в Finance тоже заполняются 95000.
✅ Но на самом деле в HR могли быть более высокие зарплаты, а мы по сути искусственно “усекли” распределение зарплат, заменив пропуски фиксированной медианой.
👉 Такая замена снижает дисперсию и искажает среднее, особенно если выборка мала.
---
💡 Правильный подход:
1. Вместо заполнения медианой, использовать **множественную имputation** (например, через `sklearn.impute.IterativeImputer`).
2. Либо **не заполнять NaN при вычислении среднего**, а использовать `mean(skipna=True)`, чтобы не “усекать” данные.
3. Либо **показать доверительный интервал** для среднего по каждой группе.
Пример альтернативного подхода:
```python
top_department = df.groupby('department')['salary'].mean().idxmax()
print(top_department)
```
✅ Таким образом NaN просто не участвуют в расчёте среднего, и мы не искажаем данные искусственным заполнением.
---
🔥 Усложнение (ещё один подвох):
А что если пропуски не случайны?
Например, все высокие зарплаты в HR отсутствуют, потому что сотрудники не раскрыли данные?
→ Тогда импутация медианой дополнительно “занижает” зарплаты HR, и классическая mean() даёт biased estimate.
В таком случае нужна модель пропусков (MAR, MCAR, MNAR) и специфические методы восстановления.
---
📝 Что проверяет задача:
✅ Понимание влияния методов заполнения пропусков
✅ Знание статистических эффектов усечения данных
✅ Умение интерпретировать результат с учётом bias
✅ Навык выбирать подходящий метод обработки пропусков в зависимости от их природы
BY Анализ данных (Data analysis)
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/data_analysis_ml/3540